package xin.alum.aim.model;

import com.google.protobuf.Any;
import com.google.protobuf.Descriptors;
import com.google.protobuf.Message;
import lombok.Data;
import lombok.SneakyThrows;
import xin.alum.aim.AIM;
import xin.alum.aim.model.proto.Packet;
import xin.alum.aim.model.proto.ProtoJsonUtil;
import xin.alum.aim.util.GZipUtil;

import java.io.Serializable;
import java.util.List;

/**
 * 数据通信抽象类
 */
@Data
abstract class DBase<T extends Message> extends Transportable implements Serializable {

    /**
     * 请求key
     */
    private String key = "";

    /**
     * 返回数据集合
     */
    protected T data;

    public DBase() {
    }

    public DBase(String key) {
        this.key = key;
        this.retain();
    }

    public DBase(String key, long timestamp) {
        this.key = key;
        super.setTimestamp(timestamp);
    }

    /**
     * 转换ProtoBuf
     *
     * @return
     */
    @Override
    public abstract Message toBuilder();

    /**
     * 将Data解包成Message对象
     *
     * @param clazz 解包目录类
     * @return
     */
    @SneakyThrows
    public T unpack(Class<T> clazz) {
        return ((Any) data).unpack(clazz);
    }

    /**
     * @return
     */
    @Override
    public byte[] getBody() {
        return GZipUtil.gzip(AIM.properties.getGzip(), toBuilder().toByteArray());
    }


    /**
     * 默认Protobuf转JSON
     *
     * @return
     */
    public String toJson() {
        return toJson(Packet.Data.getDescriptor());
    }

    @SneakyThrows
    private String toJson(ProtoJsonUtil protoJsonUtil) {
        String r = protoJsonUtil.toJson(toBuilder());
        return GZipUtil.gzip(AIM.properties.getGzip(), r);
    }

    /**
     * 自定义Protobuf转Json
     *
     * @param anyFieldDescriptor
     * @return
     */
    @SneakyThrows
    public String toJson(Descriptors.Descriptor anyFieldDescriptor) {
        return toJson(new ProtoJsonUtil(anyFieldDescriptor));
    }

    /**
     * 自定义Protobuf转Json
     *
     * @param anyFieldDescriptor
     * @return
     */
    @SneakyThrows
    public String toJson(List<Descriptors.Descriptor> anyFieldDescriptor) {
        return toJson(new ProtoJsonUtil(anyFieldDescriptor));
    }
}
